package com.example.teesystem.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.teesystem.common.exception.CustomException;
import com.example.teesystem.common.utils.PermissionUtil;
import com.example.teesystem.common.utils.Response;
import com.example.teesystem.common.utils.ResultCode;
import com.example.teesystem.entity.AdvancedTraining;
import com.example.teesystem.entity.Chapter;
import com.example.teesystem.entity.TrainIssueRelation;
import com.example.teesystem.entity.vo.PageResponseVo;
import com.example.teesystem.entity.vo.advancedTrain.AdAnswer;
import com.example.teesystem.entity.vo.advancedTrain.AdTrainRes;
import com.example.teesystem.entity.vo.advancedTrain.AdvancedTrainUpdateVo;
import com.example.teesystem.entity.vo.advancedTrain.AdvancedTrainUploadVo;
import com.example.teesystem.filter.MyHandlerInterceptor;
import com.example.teesystem.mapper.ChapterMapper;
import com.example.teesystem.mapper.TrainIssueRelationMapper;
import com.example.teesystem.service.AdvancedTrainingProgressService;
import com.example.teesystem.service.AdvancedTrainingService;
import com.example.teesystem.mapper.AdvancedTrainingMapper;
import com.example.teesystem.service.TrainIssueRelationService;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author 28131
* @description 针对表【t_advanced_training】的数据库操作Service实现
* @createDate 2022-03-31 08:09:45
*/
@Service
@AllArgsConstructor
public class AdvancedTrainingServiceImpl extends ServiceImpl<AdvancedTrainingMapper, AdvancedTraining>
    implements AdvancedTrainingService{

    private final AdvancedTrainingMapper advancedTrainingMapper;
    private final TrainIssueRelationService trainIssueRelationService;
    private final AdvancedTrainingProgressService advancedTrainingProgressService;
    private final ChapterMapper chapterMapper;
    private final TrainIssueRelationMapper trainIssueRelationMapper;
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Response add(AdvancedTrainUploadVo advancedTrainUploadVo) {
        try{
            if(advancedTrainUploadVo.getPreAdvancedTraining() == null){
                AdvancedTraining advancedTraining = advancedTrainingMapper.getAdvancedTrainingFirstNode(advancedTrainUploadVo.getCourseId(),advancedTrainUploadVo.getChapterId());
                if(advancedTraining != null){
                    return Response.error(ResultCode.FIRST_NODE_EXIST);
                }else {
                    AdvancedTraining advancedTraining1 = new AdvancedTraining();
                    BeanUtils.copyProperties(advancedTrainUploadVo,advancedTraining1);
                    advancedTraining1.setIsOpen(1);
                    advancedTraining1.setUpdateId(MyHandlerInterceptor.getUid());
                    advancedTrainingMapper.insert(advancedTraining1);
                    List<TrainIssueRelation> relations = advancedTrainUploadVo.getIssueIds().stream()
                            .map(issueId -> new TrainIssueRelation(advancedTraining1.getId(), issueId))
                            .collect(Collectors.toList());
                    this.trainIssueRelationService.saveBatch(relations);
                    return Response.ok();
                }
            }else {
                AdvancedTraining check = advancedTrainingMapper.getAdvancedTrainingNodeById(advancedTrainUploadVo.getPreAdvancedTraining());
                if(check == null){
                    return Response.error(ResultCode.PRE_NODE_NOT_EXIST);
                }
                AdvancedTraining advancedTraining = advancedTrainingMapper.getAdvancedTrainingMiddleNode(advancedTrainUploadVo.getCourseId(),advancedTrainUploadVo.getChapterId(),advancedTrainUploadVo.getPreAdvancedTraining());
                if(advancedTraining != null){
                    return Response.error(ResultCode.WARNING_NODE);
                }else {
                    AdvancedTraining advancedTraining1 = new AdvancedTraining();
                    BeanUtils.copyProperties(advancedTrainUploadVo,advancedTraining1);
                    advancedTraining1.setUpdateId(MyHandlerInterceptor.getUid());
                    advancedTraining1.setIsOpen(0);
                    advancedTrainingMapper.insert(advancedTraining1);
                    List<TrainIssueRelation> relations = advancedTrainUploadVo.getIssueIds().stream()
                            .map(issueId -> new TrainIssueRelation(advancedTraining1.getId(), issueId))
                            .collect(Collectors.toList());
                    this.trainIssueRelationService.saveBatch(relations);
                    return Response.ok();
                }
            }
        }catch (Exception e){
            System.out.println(e.getMessage());
            return Response.error(ResultCode.INSERT_ERROR);
        }

    }
    
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean update(AdvancedTrainUpdateVo advancedTrainUpdateVo) {
        try{
            // 查询是否有该进阶训练
            if(this.getById(advancedTrainUpdateVo.getId()) == null) {
                throw new CustomException(ResultCode.UPDATE_INFO_FAIL);
            }
            AdvancedTraining advancedTraining = advancedTrainingMapper.getAdvancedTrainingNodeById(advancedTrainUpdateVo.getId());
            if(advancedTraining.getPreAdvancedTraining() == 0 && advancedTrainUpdateVo.getIsOpen() ==0 ){
                throw new CustomException(ResultCode.FIRST_NODE_NOT_UPDATE);
            }
            // 如果有则首先删除训练题目关系表中已有的题目
            QueryWrapper<TrainIssueRelation> wrapper = new QueryWrapper<>();
            wrapper.eq("ad_train_id", advancedTrainUpdateVo.getId());
            trainIssueRelationMapper.deleteIssue(advancedTraining.getId());
            advancedTrainingMapper.updateMessage(advancedTrainUpdateVo.getMessage(),advancedTrainUpdateVo.getId(),advancedTrainUpdateVo.getIsOpen());
            // 然后重新保存新的题目
            if(advancedTrainUpdateVo.getIssueIds() == null||advancedTrainUpdateVo.getIssueIds().size()==0) {
                return true;
            }
            List<TrainIssueRelation> relations = advancedTrainUpdateVo.getIssueIds().stream()
                    .map(issueId -> new TrainIssueRelation(advancedTrainUpdateVo.getId(), issueId))
                    .collect(Collectors.toList());
            return this.trainIssueRelationService.saveBatch(relations);
        }catch (Exception e){
            System.out.println(e.getMessage());
            return false;
        }

    }
    
    @Override
    public boolean delete(List<Integer> ids) {
        int courseId;
        for(int i = 0; i<ids.size(); i++){
            courseId = this.getCourseId(ids.get(0));
            if(!PermissionUtil.permissionCheck(MyHandlerInterceptor.getUid(),PermissionUtil.ADVANCED_TRAINING_MANAGE,courseId)) {
                throw new CustomException(ResultCode.NO_PERMISSION);
            }
        }
        
        if(!this.removeBatchByIds(ids)) {
            throw new CustomException(ResultCode.DELETE_INFO_FAIL);
        }
        QueryWrapper<TrainIssueRelation> wrapper = new QueryWrapper<>();
        wrapper.in("ad_train_id", ids);
        return this.trainIssueRelationService.remove(wrapper);
    }
    
    @Override
    public List<List<AdTrainRes>> get(Integer courseId) {
        List<Chapter> chapters = chapterMapper.selectAllByCourseId(courseId);
        List<List<AdTrainRes>> listAdTrainList = new ArrayList<>();
        for (Chapter chapter : chapters) {
            AdTrainRes adTrainRes1 = advancedTrainingMapper.getAdvancedTrainingFirstNodeAdTrain(courseId, chapter.getId());
            List<AdTrainRes> adTrainRes = new ArrayList<>();
            while (adTrainRes1 != null) {
                adTrainRes1.setChapterMsg(chapter.getMessage());
                adTrainRes.add(adTrainRes1);
                adTrainRes1 = advancedTrainingMapper.getAdvancedTrainingMiddleNodeAdTrain(courseId, chapter.getId(), adTrainRes1.getId());
            }
            listAdTrainList.add(adTrainRes);
        }
        return listAdTrainList;
    }

    @Override
    public int getCourseId(int id) {
        try{
            return advancedTrainingMapper.getCourseId(id);
        }catch (Exception e){
            return 0;
        }
    }
    
    @Override
    public List<Integer> getIssues(Integer id) {
        QueryWrapper<TrainIssueRelation> wrapper = new QueryWrapper<>();
        wrapper.eq("ad_train_id", id);
        return this.trainIssueRelationService.list(wrapper).stream()
                .map(TrainIssueRelation::getIssueId)
                .collect(Collectors.toList());
    }

    @Override
    public Response deleteAdvancedTraining(int id) {
        try{
            AdvancedTraining advancedTraining = advancedTrainingMapper.getAdvancedTrainingNodeById(id);
            if(advancedTraining == null) {
                return Response.error(ResultCode.LOG_NOT_EXIST);
            } else {
                AdvancedTraining advancedTraining1 = advancedTrainingMapper.getAdvancedTrainingMiddleNode(advancedTraining.getCourseId(),advancedTraining.getChapterId(),id);
                if(advancedTraining1 != null){
                    return Response.error(ResultCode.NODE_NOT_DELETE);
                }else {
                    advancedTrainingMapper.deleteAdvancedTraining(id);
                    return Response.ok();
                }
            }
        }catch (Exception e){
            return Response.error(ResultCode.DELETE_INFO_FAIL);
        }
    }


    /**
     * 检验进阶训练是否唯一（章节 id 和 课程 id）
     * @param courseId 课程 id
     * @param chapterId 章节 id
     * @return 不唯一返回 true
     */
    private boolean validAdTrainExist(Integer courseId, Integer chapterId) {
        QueryWrapper<AdvancedTraining> wrapper = new QueryWrapper<>();
        wrapper.eq("course_id", courseId)
                .eq("chapter_id", chapterId);
        return this.count(wrapper) != 0;
    }
}
